﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace InverseKinematics
{
    public class Cuboid
    {

         // UV 
        Vector2 textureTopLeft = new Vector2(1.0f, 0.0f);
        Vector2 textureTopRight = new Vector2(0.0f, 0.0f);
        Vector2 textureBottomLeft = new Vector2(1.0f, 1.0f);
        Vector2 textureBottomRight = new Vector2(0.0f, 1.0f);
        Matrix m;
        const int NUM_TRIANGLES = 12;
        const int NUM_VERTICES = 36;

    

        // Array of vertex information - contains position and normal data
        private VertexPositionNormalTexture[] vertices;
        private VertexPositionNormalTexture[] originalVertices;
        
        public Vector3 Texture { get; set; }
        private Vector3[] positions;
        private Vector3[] normals;

        public Cuboid()
        {
            m = Matrix.Identity;
            vertices = new VertexPositionNormalTexture[NUM_VERTICES];
            positions = new Vector3[8];
            positions[0] = new Vector3(-1.0f, 1.0f, -1.0f);
            positions[1] = new Vector3(-1.0f, 1.0f, 1.0f);
            positions[2] = new Vector3(1.0f, 1.0f, -1.0f);
            positions[3] = new Vector3(1.0f, 1.0f, 1.0f);
            positions[4] = new Vector3(-1.0f, -1.0f, -1.0f);
            positions[5] = new Vector3(-1.0f, -1.0f, 1.0f);
            positions[6] = new Vector3(1.0f, -1.0f, -1.0f);
            positions[7] = new Vector3(1.0f, -1.0f, 1.0f);

            normals = new Vector3[6];
            normals[0] = new Vector3(0.0f, 0.0f, 1.0f);
            normals[1] = new Vector3(0.0f, 0.0f, -1.0f);
            normals[2] = new Vector3(0.0f, 1.0f, 0.0f);
            normals[3] = new Vector3(0.0f, -1.0f, 0.0f);
            normals[4] = new Vector3(-1.0f, 0.0f, 0.0f);
            normals[5] = new Vector3(1.0f, 0.0f, 0.0f);
            ConstructCube();
        }

        public void Update()
        {
            for (int i = 0; i < vertices.Length; i++)
            {
                Vector3.Transform(ref originalVertices[i].Position, ref m, out vertices[i].Position);
                Vector3.Transform(ref originalVertices[i].Normal, ref m, out vertices[i].Normal);
            }
            foreach (VertexPositionNormalTexture vertex in vertices) vertex.Normal.Normalize(); 

            m = Matrix.Identity;
        }


        /// <summary>
        /// Writes our list of vertices to the vertex buffer, 
        /// then draws triangles to the device
        /// </summary>
        /// <param name="device"></param>
        public void Draw(GraphicsDevice device)
        {
 

            using (VertexBuffer buffer = new VertexBuffer(
                device,
                VertexPositionNormalTexture.VertexDeclaration,
                NUM_VERTICES,
                BufferUsage.WriteOnly))
            {
                // load the buffer
                buffer.SetData(vertices);

                // send the vertex buffer to the device
                device.SetVertexBuffer(buffer);
            }

            device.DrawPrimitives(PrimitiveType.TriangleList, 0, NUM_TRIANGLES);
        }

        public void Rotate(Vector3 r)
        {
            m *= Matrix.CreateFromYawPitchRoll(r.Y, r.X, r.Z);         
        }

        public void Scale(Vector3 v)
        {
            m *= Matrix.CreateScale(v);
        }

        public void Translate(Vector3 t)
        {
            m *= Matrix.CreateTranslation(t);
        }

        public void Transform(Matrix m)
        {
            this.m *= m;
        }


        private void ConstructCube()
        {

            // Add the vertices for the FRONT face.
            vertices[0] = new VertexPositionNormalTexture(positions[0], normals[0], textureTopLeft);
            vertices[1] = new VertexPositionNormalTexture(positions[4], normals[0], textureBottomLeft);
            vertices[2] = new VertexPositionNormalTexture(positions[2], normals[0], textureTopRight);
            vertices[3] = new VertexPositionNormalTexture(positions[4], normals[0], textureBottomLeft);
            vertices[4] = new VertexPositionNormalTexture(positions[6], normals[0], textureBottomRight);
            vertices[5] = new VertexPositionNormalTexture(positions[2], normals[0], textureTopRight);

            // Add the vertices for the BACK face.
            vertices[6] = new VertexPositionNormalTexture(positions[1], normals[1], textureTopRight);
            vertices[7] = new VertexPositionNormalTexture(positions[3], normals[1], textureTopLeft);
            vertices[8] = new VertexPositionNormalTexture(positions[5], normals[1], textureBottomRight);
            vertices[9] = new VertexPositionNormalTexture(positions[5], normals[1], textureBottomRight);
            vertices[10] = new VertexPositionNormalTexture(positions[3], normals[1], textureTopLeft);
            vertices[11] = new VertexPositionNormalTexture(positions[7], normals[1], textureBottomLeft);

            // Add the vertices for the TOP face.
            vertices[12] = new VertexPositionNormalTexture(positions[0], normals[2], textureBottomLeft);
            vertices[13] = new VertexPositionNormalTexture(positions[3], normals[2], textureTopRight);
            vertices[14] = new VertexPositionNormalTexture(positions[1], normals[2], textureTopLeft);
            vertices[15] = new VertexPositionNormalTexture(positions[0], normals[2], textureBottomLeft);
            vertices[16] = new VertexPositionNormalTexture(positions[2], normals[2], textureBottomRight);
            vertices[17] = new VertexPositionNormalTexture(positions[3], normals[2], textureTopRight);

            // Add the vertices for the BOTTOM face. 
            vertices[18] = new VertexPositionNormalTexture(positions[4], normals[3], textureTopLeft);
            vertices[19] = new VertexPositionNormalTexture(positions[5], normals[3], textureBottomLeft);
            vertices[20] = new VertexPositionNormalTexture(positions[7], normals[3], textureBottomRight);
            vertices[21] = new VertexPositionNormalTexture(positions[4], normals[3], textureTopLeft);
            vertices[22] = new VertexPositionNormalTexture(positions[7], normals[3], textureBottomRight);
            vertices[23] = new VertexPositionNormalTexture(positions[6], normals[3], textureTopRight);

            // Add the vertices for the LEFT face.
            vertices[24] = new VertexPositionNormalTexture(positions[0], normals[4], textureTopRight);
            vertices[25] = new VertexPositionNormalTexture(positions[5], normals[4], textureBottomLeft);
            vertices[26] = new VertexPositionNormalTexture(positions[4], normals[4], textureBottomRight);
            vertices[27] = new VertexPositionNormalTexture(positions[1], normals[4], textureTopLeft);
            vertices[28] = new VertexPositionNormalTexture(positions[5], normals[4], textureBottomLeft);
            vertices[29] = new VertexPositionNormalTexture(positions[0], normals[4], textureTopRight);

            // Add the vertices for the RIGHT face. 
            vertices[30] = new VertexPositionNormalTexture(positions[2], normals[5], textureTopLeft);
            vertices[31] = new VertexPositionNormalTexture(positions[6], normals[5], textureBottomLeft);
            vertices[32] = new VertexPositionNormalTexture(positions[7], normals[5], textureBottomRight);
            vertices[33] = new VertexPositionNormalTexture(positions[3], normals[5], textureTopRight);
            vertices[34] = new VertexPositionNormalTexture(positions[2], normals[5], textureTopLeft);
            vertices[35] = new VertexPositionNormalTexture(positions[7], normals[5], textureBottomRight);

            originalVertices = (VertexPositionNormalTexture[])vertices.Clone();
        }


    }
}
